import LXCOM from '../../common/common.js'
import baseGraph from '../baseunitgrah.js'
import { CoordTRFUtil } from '../../common/tools/coordtool.js'
import Coord from '../../common/struct/coord.js'
import utilfuncs from '../../common/tools/utilfuncs.js'
var funcs = utilfuncs.UtilFuncs
import GlobalConst from '../../common/globalConst.js'
var global = GlobalConst.GlobalConst;
import { FillUtil } from '../../graph/paintutil/fillutil.js'
import { Strokeutil } from '../../graph/paintutil/strokeutil.js'

import { LGXEnums } from '../../common/sysenum.js'


import specialrect from '../../common/struct/basestruct/specialrect.js'
import singlepointaction from '../action/singlepointaction.js'
import { GlobalVar } from '../../common/globalvar.js'
import absgraph from '../absgraph.js'

class RectSecInfo {
    constructor() {
        this.st = { x: 0, y: 0 };
        this.end = { x: 0, y: 0 };
        this.kind = 0;
        this.index = 0;//顶点索引
    }
}

const CtrlPointKind = 1000;
//GlobalConst.SpecialRectType = 0x0334xxxx;//带切角的特殊矩形
//低四位16进制
//，第四位表示左上角点的装饰类型，0默认，不切；1--表示倒直角；2-表示倒圆角
//，第四位表示左下角点的装饰类型，0默认，不切；1--表示倒直角；2-表示倒圆角
//，第四位表示右下角点的装饰类型，0默认，不切；1--表示倒直角；2-表示倒圆角
//，第四位表示右上角点的装饰类型，0默认，不切；1--表示倒直角；2-表示倒圆角
class SpecialRectangleGraph extends baseGraph.BaseUnitGraph {
    constructor(type) {
        super(type);
        this.m_graphType = LGXEnums.LGXGraphType.SpecialRect_type;
        var pos = new Coord.PointPos();
        this.setPos(pos);
        this.width = 120;
        this.height = 120;
        this.chamferSize = [20, 20, 20, 20];//倒角尺寸
        //左上角、左下角、右下角、右上角
        this.ctrlPointList = [{ x: 0, y: 0 }, { x: 0, y: 0 }, { x: 0, y: 0 }, { x: 0, y: 0 }];
        this.vertexKindList = [0, 0, 0, 0];
        this.sectionList = [];
        var action = new singlepointaction.SinglePointAction(this);
        this.setActionSvc(action);
        this._fillDef.fillStyle = LGXEnums.LGXFillStyle.SOLID;
        this._fillDef.fillColor.clone(GlobalVar.visoDefaultFillColor);
    }

    display(map, mapInfo, forClip) {
        var trfFunc = this.convertWorldPt2Screen;
        this.paint(trfFunc, map, mapInfo, forClip);
    }

    disInSymbol(transformInfo, map, mapInfo, forClip) {
        var trfFunc = this.convertLocalPt2Screen;
        this.paint(trfFunc, map, mapInfo, forClip, transformInfo);
    }

    paint(trfFunc, map, mapInfo, forClip, transformInfo) {
        let rotv = this.getRadAngle();
        let preTransformRotValue = 0;
        if (transformInfo) {
            preTransformRotValue = transformInfo.rotRad;
            rotv += transformInfo.rotRad;
            transformInfo.rotRad = 0;
        }
        var cntScreenPT = trfFunc(this._position, mapInfo, transformInfo);
        map.save();
        map.translate(cntScreenPT.x, cntScreenPT.y);
        map.rotate(-rotv);
        map.translate(-cntScreenPT.x, -cntScreenPT.y);

        map.beginPath();
        let secCount = this.sectionList.length;
        for (let i = 0; i < secCount; i++) {
            let secInfo = this.sectionList[i];
            this.paintSingleSec(trfFunc, i, secInfo, map, mapInfo, transformInfo);
        }
        map.closePath();
        let paintSymFlag = false;
        if (transformInfo) {
            paintSymFlag = true;
        }

        if (!forClip) {
            Strokeutil.active(this._lineDef, this, map, mapInfo);
            FillUtil.active(this._fillDef, map, this, mapInfo, paintSymFlag, transformInfo);
        }
        map.restore();

        if (!transformInfo) {
            super.displayGraphScope(map, mapInfo);
            this.displayFeaturePoint(map, mapInfo);
        }
        else {
            transformInfo.rotRad = preTransformRotValue;
        }
    }

    paintSingleSec(trfFunc, secIdx, secInfo, map, mapInfo, transformInfo) {
        if (secInfo.kind == 0 || secInfo.kind == 1) {
            let p1 = trfFunc(secInfo.st, mapInfo, transformInfo);
            let p2 = trfFunc(secInfo.end, mapInfo, transformInfo);
            if (secIdx == 0) {
                map.moveTo(p1.x, p1.y);
            }
            map.lineTo(p2.x, p2.y);
        }
        else {
            let index = secInfo.index;//顶点索引
            let scaling = mapInfo.getLenthDisScale();
            let halfwid = this.width / 2;
            let halfhgt = this.height / 2;

            let position = this.getPos();
            let cntPt = { x: position.x, y: position.y };

            let x = 0;
            let y = 0;
            let radius = this.chamferSize[index];
            if (index == 0) {
                x = cntPt.x - halfwid + radius;
                y = cntPt.y + halfhgt - radius;
            }
            else if (index == 1) {
                x = cntPt.x - halfwid + radius;
                y = cntPt.y - halfhgt + radius;
            }
            else if (index == 2) {
                x = cntPt.x + halfwid - radius;
                y = cntPt.y - halfhgt + radius;
            }
            else if (index == 3) {
                x = cntPt.x + halfwid - radius;
                y = cntPt.y + halfhgt - radius;
            }

            let stDgree = 90 * (index + 1);
            if (stDgree == 360) {
                stDgree = 0;
            }
            let endDegree = stDgree + 90;
            let stAngleRad = Math.PI * 2 - funcs.degree2Radian(stDgree);
            let endAngleRad = Math.PI * 2 - funcs.degree2Radian(endDegree);

            let screenArcCntPt = trfFunc({ x, y }, mapInfo, transformInfo);
            let disXRadius = radius * scaling;
            let disYRadius = radius * scaling;
            if (transformInfo) {
                disXRadius *= transformInfo.sx;
                disYRadius *= transformInfo.sy;
            }
            // map.arc(screenArcCntPt.x, screenArcCntPt.y, disRadius, stAngleRad, endAngleRad, true);
            map.ellipse(screenArcCntPt.x, screenArcCntPt.y, disXRadius, disYRadius, 0,
                stAngleRad, endAngleRad, true);

        }
    }

    calScope(mapscale) {
        let fullType = this.getType();
        let leftTopKind = fullType & 0x0000f000;
        this.vertexKindList[0] = leftTopKind >> 12;

        let leftBottomKind = fullType & 0x00000f00;
        this.vertexKindList[1] = leftBottomKind >> 8;

        let rightBotKind = fullType & 0x000000f0;
        this.vertexKindList[2] = rightBotKind >> 4;

        let rightTopKind = fullType & 0x0000000f;
        this.vertexKindList[3] = rightTopKind;

        this.calSpecialSec();

        let mtx = this.getLocalMatrix();

        let ptlist = [];
        let localLTPt = { x: 0, y: 0, z: 0 };
        localLTPt.x = -this.width / 2;
        localLTPt.y = this.height / 2;
        let ltWorldPt = mtx.MultT(localLTPt);//局部坐标左上角转为世界坐标
        ptlist.push(ltWorldPt);

        let localLbPt = { x: 0, y: 0, z: 0 };
        localLbPt.x = -this.width / 2;
        localLbPt.y = -this.height / 2;
        let lbWorldPt = mtx.MultT(localLbPt);//局部坐标左下角转为世界坐标
        ptlist.push(lbWorldPt);

        let localRBPt = { x: 0, y: 0, z: 0 };
        localRBPt.x = this.width / 2;
        localRBPt.y = -this.height / 2;
        let rbWorldPt = mtx.MultT(localRBPt);//局部坐标右下角转为世界坐标
        ptlist.push(rbWorldPt);

        let localRTPt = { x: 0, y: 0, z: 0 };
        localRTPt.x = this.width / 2;
        localRTPt.y = this.height / 2;
        let rTWorldPt = mtx.MultT(localRTPt);//局部坐标右下角转为世界坐标
        ptlist.push(rTWorldPt);

        this._zone.clone(funcs.calPtListZone(ptlist));
    }

    getLocalZone() {
        let rect = new LXCOM.LGXRect(0, 0, 0, 0);
        rect.left = (- this.width / 2);
        rect.bottom = (- this.height / 2);
        rect.right = (this.width / 2);
        rect.top = (this.height / 2);
        return rect;
    }

    displayFeaturePoint(map, mapInfo) {
        if (!this._selected || mapInfo.paintForGenerateICON) {
            return;
        }
        var ptlst = this.getScopeVertexPtLst(mapInfo.getScaling());
        this.displayDashLineRectScope(ptlst, map, mapInfo)
        ptlst.length = 0;
        ptlst = null;

        for (let i = 0; i < 4; i++) {
            if (this.vertexKindList[i] != 0) {
                let pt = this.ctrlPointList[i];
                let spt = CoordTRFUtil.world2Screen(pt, mapInfo);
                this.drawFocusPoint(map, spt.x, spt.y, "#ffff00");
            }
        }
    }

    distance(tPoint, scaling, mapscale) {
        if (!super.preCheckInScope(tPoint, scaling)) {
            return -1;
        }
        return 0;
    }

    calculateSubKind(tPoint, scaling, mapscale) {
        if (!super.preCheckInScope(tPoint, scaling)) {
            return 0;
        }
        var seleKind = 0;
        var tAbsorbPt = new LXCOM.LGXPoint();
        tAbsorbPt.clone(tPoint);

        let minDis = 100;
        var cmpGap = super.getSelCmpGap(scaling, mapscale);

        for (let i = 0; i < 4; i++) {
            if (this.vertexKindList[i] != 0) {
                let pt = this.ctrlPointList[i];
                let dis = funcs.distancePoint(tPoint, pt, scaling);
                if (dis <= cmpGap && dis >= 0 && dis <= minDis) {
                    minDis = dis;
                    tAbsorbPt.clone(pt);
                    seleKind = CtrlPointKind + i;
                }
            }
        }

        if (seleKind > 0) {
            tPoint.clone(tAbsorbPt);
        }
        else {
            seleKind = 1;
        }

        return seleKind;
    }

    movePosOffset(tOffset, modCmdInfo) {
        if (this._selKind < 1) {
            return;
        }
        if (this._selKind == 1) {
            this.translate(tOffset, modCmdInfo.mapscale, false);
        }
        else if (this._selKind >= CtrlPointKind) {
            let selVertIdx = this._selKind - CtrlPointKind;
            let tmp = this.chamferSize[selVertIdx] + tOffset.x;
            if (selVertIdx == 2 || selVertIdx == 3) {
                tmp = this.chamferSize[selVertIdx] - tOffset.x;
            }
            let maxSize = this.width / 2;
            if (maxSize > this.height / 2) {
                maxSize = this.height / 2;
            }
            if (tmp > global.ZERO_4E && tmp < maxSize) {
                this.chamferSize[selVertIdx] = tmp;
            }
        }
    }

    translate(tOffset, mapscale, multiTransFlag, mulSelLineList) {
        let preCnt = this._position.getCnt();
        this._position.offset(tOffset.x, tOffset.y);
        this.calScope(mapscale);
        this.translateGradientFill(tOffset);
        this.translateAttachInfo(preCnt, tOffset, mapscale, multiTransFlag, mulSelLineList);
        return 0;
    }

    getMainFeaturePTLst(tFeaturePTLst, transformInfo) {
        let position = this.getPosCopy();
        let cntPt = { x: position.x, y: position.y };
        let featurePT = this.convertPt2World(cntPt, transformInfo);
        tFeaturePTLst.push({ pt: featurePT, kind: LGXEnums.AuxPointKind.center });
        for (let i = 0; i < this.sectionList.length; i++) {
            let secInfo = this.sectionList[i];
            tFeaturePTLst.push({ pt: secInfo.st, kind: LGXEnums.AuxPointKind.end });
            tFeaturePTLst.push({ pt: secInfo.end, kind: LGXEnums.AuxPointKind.end });

            let x = (secInfo.st.x + secInfo.end.x) / 2;
            let y = (secInfo.st.y + secInfo.end.y) / 2;
            let featurePT = this.convertPt2World({ x, y }, transformInfo);
            tFeaturePTLst.push({ pt: featurePT, kind: LGXEnums.AuxPointKind.lineMid });
        }

        let halfwid = this.width / 2;
        let halfhgt = this.height / 2;

        //外框左侧中点
        let x = cntPt.x - halfwid;
        let y = cntPt.y;
        featurePT = this.convertPt2World({ x, y }, transformInfo);
        tFeaturePTLst.push({ pt: featurePT, kind: LGXEnums.AuxPointKind.lineMid });

        //外框右侧中点
        x = cntPt.x + halfwid;
        y = cntPt.y;
        featurePT = this.convertPt2World({ x, y }, transformInfo);
        tFeaturePTLst.push({ pt: featurePT, kind: LGXEnums.AuxPointKind.lineMid });

        //外框顶边中点
        x = cntPt.x;
        y = cntPt.y + halfhgt;
        featurePT = this.convertPt2World({ x, y }, transformInfo);
        tFeaturePTLst.push({ pt: featurePT, kind: LGXEnums.AuxPointKind.lineMid });

        //外框底边中点
        x = cntPt.x;
        y = cntPt.y - halfhgt;
        featurePT = this.convertPt2World({ x, y }, transformInfo);
        tFeaturePTLst.push({ pt: featurePT, kind: LGXEnums.AuxPointKind.lineMid });
    }


    assignInfo(info) {
        super.assignInfo(info);
        this.width = info.width;
        this.height = info.height;
        this.chamferSize[0] = info.chamferSize1;//左上倒角尺寸
        this.chamferSize[1] = info.chamferSize2;//左下倒角尺寸
        this.chamferSize[2] = info.chamferSize3;//右下倒角尺寸
        this.chamferSize[3] = info.chamferSize4;//右上倒角尺寸
    }

    modifyAttribute(info, mapscale) {
        super.modifyCommonAttribute(info);
        this.width = info.width;
        this.height = info.height;
        this.chamferSize[0] = info.chamferSize1;//左上倒角尺寸
        this.chamferSize[1] = info.chamferSize2;//左下倒角尺寸
        this.chamferSize[2] = info.chamferSize3;//右下倒角尺寸
        this.chamferSize[3] = info.chamferSize4;//右上倒角尺寸
        this.calScope(mapscale);
    }

    toInfo() {
        var info = new specialrect.SpecialRect();
        this.toInfo4InheritClass(info);
        let position = this.getPos();
        info.x = position.x;
        info.y = position.y;
        info.width = this.width;
        info.height = this.height;
        info.chamferSize1 = this.chamferSize[0];//左上倒角尺寸
        info.chamferSize2 = this.chamferSize[1];//左下倒角尺寸
        info.chamferSize3 = this.chamferSize[2];//右下倒角尺寸
        info.chamferSize4 = this.chamferSize[3];//右上倒角尺寸
        return info;
    }

    rotateCoord(rotCnt, radAngle) {
        var position = this.getPos();
        var p1 = funcs.rotate(position, rotCnt, radAngle);
        position.clone(p1);
        super.rotateGradientFill(rotCnt, radAngle);
        this.rotateConnTopo(rotCnt, radAngle);

        for (let i = 0; i < 4; i++) {
            if (this.vertexKindList[i] != 0) {
                let pt = this.ctrlPointList[i];
                var p1 = funcs.rotate(pt, rotCnt, radAngle);
                this.ctrlPointList[i].x = p1.x;
                this.ctrlPointList[i].y = p1.y;
            }
        }
    }

    calSpecialSec() {
        this.sectionList = [];
        let halfwid = this.width / 2;
        let halfhgt = this.height / 2;

        let position = this.getPos();
        let cntPt = { x: position.x, y: position.y };

        this.calLeftTopVertInfo(cntPt, halfwid, halfhgt);
        this.calLeftBottomVertInfo(cntPt, halfwid, halfhgt);
        this.calRightBottomVertInfo(cntPt, halfwid, halfhgt);
        this.calRightTopVertInfo(cntPt, halfwid, halfhgt);
    }

    calLeftTopVertInfo(cntPt, halfwid, halfhgt) {
        if (this.vertexKindList[0] == 0) {
            let x = cntPt.x - halfwid;
            let y = cntPt.y + halfhgt;
            let t = new RectSecInfo();
            t.st.x = x;
            t.st.y = y;
            t.kind = 0;

            if (this.vertexKindList[1] == 0) {
                t.end.x = cntPt.x - halfwid;
                t.end.y = cntPt.y - halfhgt;
            }
            else {
                t.end.x = cntPt.x - halfwid;
                t.end.y = cntPt.y - halfhgt + this.chamferSize[1];
            }
            this.sectionList.push(t);
        }
        else if (this.vertexKindList[0] > 0) {
            let x = cntPt.x - halfwid + this.chamferSize[0];
            let y = cntPt.y + halfhgt;
            let t = new RectSecInfo();
            t.st.x = x;
            t.st.y = y;
            t.kind = this.vertexKindList[0];
            t.index = 0;
            this.ctrlPointList[0].x = x;
            this.ctrlPointList[0].y = y;

            t.end.x = cntPt.x - halfwid;
            t.end.y = cntPt.y + halfhgt - this.chamferSize[0];
            this.sectionList.push(t);

            let nextInfo = new RectSecInfo();
            nextInfo.st.x = t.end.x;
            nextInfo.st.y = t.end.y;
            nextInfo.kind = 0;

            if (this.vertexKindList[1] == 0) {
                nextInfo.end.x = cntPt.x - halfwid;
                nextInfo.end.y = cntPt.y - halfhgt;
            }
            else {
                nextInfo.end.x = cntPt.x - halfwid;
                nextInfo.end.y = cntPt.y - halfhgt + this.chamferSize[1];
            }
            this.sectionList.push(nextInfo);
        }
    }

    calLeftBottomVertInfo(cntPt, halfwid, halfhgt) {
        if (this.vertexKindList[1] == 0) {
            let x = cntPt.x - halfwid;
            let y = cntPt.y - halfhgt;
            let t = new RectSecInfo();
            t.st.x = x;
            t.st.y = y;
            t.kind = 0;

            if (this.vertexKindList[2] == 0) {
                t.end.x = cntPt.x + halfwid;
                t.end.y = cntPt.y - halfhgt;
            }
            else {
                t.end.x = cntPt.x + halfwid - this.chamferSize[1];
                t.end.y = cntPt.y - halfhgt;
            }
            this.sectionList.push(t);
        }
        else if (this.vertexKindList[1] > 0) {
            let x = cntPt.x - halfwid;
            let y = cntPt.y - halfhgt + this.chamferSize[1];
            let t = new RectSecInfo();
            t.st.x = x;
            t.st.y = y;
            t.kind = this.vertexKindList[1];
            t.index = 1;

            t.end.x = cntPt.x - halfwid + this.chamferSize[1];
            t.end.y = cntPt.y - halfhgt;
            this.sectionList.push(t);

            this.ctrlPointList[1].x = t.end.x;
            this.ctrlPointList[1].y = t.end.y;

            let nextInfo = new RectSecInfo();
            nextInfo.st.x = t.end.x;
            nextInfo.st.y = t.end.y;
            nextInfo.kind = 0;

            if (this.vertexKindList[2] == 0) {
                nextInfo.end.x = cntPt.x + halfwid;
                nextInfo.end.y = cntPt.y - halfhgt;
            }
            else {
                nextInfo.end.x = cntPt.x + halfwid - this.chamferSize[2];
                nextInfo.end.y = cntPt.y - halfhgt;
            }
            this.sectionList.push(nextInfo);
        }
    }

    calRightBottomVertInfo(cntPt, halfwid, halfhgt) {
        if (this.vertexKindList[2] == 0) {
            let x = cntPt.x + halfwid;
            let y = cntPt.y - halfhgt;
            let t = new RectSecInfo();
            t.st.x = x;
            t.st.y = y;
            t.kind = 0;

            if (this.vertexKindList[3] == 0) {
                t.end.x = cntPt.x + halfwid;
                t.end.y = cntPt.y + halfhgt;
            }
            else {
                t.end.x = cntPt.x + halfwid;
                t.end.y = cntPt.y + halfhgt - this.chamferSize[3];
            }
            this.sectionList.push(t);
        }
        else if (this.vertexKindList[2] > 0) {
            let x = cntPt.x + halfwid - this.chamferSize[2];
            let y = cntPt.y - halfhgt;
            let t = new RectSecInfo();
            t.st.x = x;
            t.st.y = y;
            t.kind = this.vertexKindList[2];
            t.index = 2;
            this.ctrlPointList[2].x = x;
            this.ctrlPointList[2].y = y;

            t.end.x = cntPt.x + halfwid;
            t.end.y = cntPt.y - halfhgt + this.chamferSize[2];
            this.sectionList.push(t);

            let nextInfo = new RectSecInfo();
            nextInfo.st.x = t.end.x;
            nextInfo.st.y = t.end.y;
            nextInfo.kind = 0;

            if (this.vertexKindList[3] == 0) {
                nextInfo.end.x = cntPt.x + halfwid;
                nextInfo.end.y = cntPt.y + halfhgt;
            }
            else {
                nextInfo.end.x = cntPt.x + halfwid;
                nextInfo.end.y = cntPt.y + halfhgt - this.chamferSize[3];
            }
            this.sectionList.push(nextInfo);
        }
    }

    calRightTopVertInfo(cntPt, halfwid, halfhgt) {
        if (this.vertexKindList[3] == 0) {
            let x = cntPt.x + halfwid;
            let y = cntPt.y + halfhgt;
            let t = new RectSecInfo();
            t.st.x = x;
            t.st.y = y;
            t.kind = 0;

            if (this.vertexKindList[0] == 0) {
                t.end.x = cntPt.x - halfwid;
                t.end.y = cntPt.y + halfhgt;
            }
            else {
                t.end.x = cntPt.x - halfwid + this.chamferSize[0];
                t.end.y = cntPt.y + halfhgt;
            }
            this.sectionList.push(t);
        }
        else if (this.vertexKindList[3] > 0) {
            let x = cntPt.x + halfwid;
            let y = cntPt.y + halfhgt - this.chamferSize[3];
            let t = new RectSecInfo();
            t.st.x = x;
            t.st.y = y;
            t.kind = this.vertexKindList[3];
            t.index = 3;

            t.end.x = cntPt.x + halfwid - this.chamferSize[3];
            t.end.y = cntPt.y + halfhgt;
            this.sectionList.push(t);
            this.ctrlPointList[3].x = t.end.x;
            this.ctrlPointList[3].y = t.end.y;

            let nextInfo = new RectSecInfo();
            nextInfo.st.x = t.end.x;
            nextInfo.st.y = t.end.y;
            nextInfo.kind = 0;

            if (this.vertexKindList[0] == 0) {
                nextInfo.end.x = cntPt.x - halfwid;
                nextInfo.end.y = cntPt.y + halfhgt;
            }
            else {
                nextInfo.end.x = cntPt.x - halfwid + this.chamferSize[0];
                nextInfo.end.y = cntPt.y + halfhgt;
            }
            this.sectionList.push(nextInfo);
        }
    }
    getPosCopy() {
        let pos = new Coord.PointPos();
        pos.clone(this._position);
        return pos;
    }

    getLocalOrigin() {
        let pt = { x: 0, y: 0 };
        pt.x = this._position.x;
        pt.y = this._position.y;
        return pt;
    }

    //复制粘贴时，从复制源对象复制属性到本图形对应属性----虚函数，由实体继承类实现
    copySubPropFromBuf(info, tx, ty) {
        this.width = info.width;
        this.height = info.height;

        this.chamferSize[0] = info.chamferSize1;
        this.chamferSize[1] = info.chamferSize2;
        this.chamferSize[2] = info.chamferSize3;
        this.chamferSize[3] = info.chamferSize4;

        this.copyCommnonPropFromBuf(info, tx, ty);
    }

    //检测point点是否落在当前图形对象的边界上
    chPtOnEdge(point, scaling) {
        let flag = false;
        let transformInfo = new absgraph.TransformInfo();
        let tFeaturePTLst = [];
        this.getMainFeaturePTLst(tFeaturePTLst, transformInfo);
        tFeaturePTLst.forEach(ele => {
            let dis = funcs.distancePoint(ele.pt, point, scaling);
            if (dis < global.SelectGap) {
                flag = true;
                return;
            }
        });
        return flag;
    }
}


export default { SpecialRectangleGraph }
